package com.lagou.session;

import com.lagou.pojo.Configuration;
import com.lagou.pojo.MapperStatement;

import java.beans.IntrospectionException;
import java.lang.reflect.*;
import java.sql.SQLException;
import java.util.List;

/**
 * @author srh
 * @date 2020/02/22
 **/
public class DefaultSqlSession implements SqlSession {

    private static final String INSERT = "insert";
    private static final String DELETE = "delete";
    private static final String UPDATE = "update";

    /**
     * 配置数据
     */
    private Configuration configuration;
    /**
     * 执行器
     */
    private Executor simpleExecutor;


    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
        this.simpleExecutor = new SimpleExecutor();
    }

    @Override
    public <T> List<T> selectList(String statementId, Object... params) throws InvocationTargetException, SQLException, IntrospectionException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        MapperStatement mapperStatement = configuration.getMapperStatementMap().get(statementId);
        return simpleExecutor.query(configuration, mapperStatement, params);
    }

    @Override
    public <T> T selectOne(String statementId, Object... params) throws InvocationTargetException, SQLException, IntrospectionException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        MapperStatement mapperStatement = configuration.getMapperStatementMap().get(statementId);
        List<T> query = simpleExecutor.query(configuration, mapperStatement, params);
        if (null != query && query.size() == 1) {
            return query.get(0);
        }
        return null;
    }

    @Override
    public int update(String statementId, Object... params) throws SQLException, NoSuchFieldException, IllegalAccessException {
        MapperStatement mapperStatement = configuration.getMapperStatementMap().get(statementId);
        return simpleExecutor.executor(configuration, mapperStatement, params);
    }

    @Override
    public int insert(String statementId, Object... params) throws SQLException, NoSuchFieldException, IllegalAccessException {
        MapperStatement mapperStatement = configuration.getMapperStatementMap().get(statementId);
        return simpleExecutor.executor(configuration, mapperStatement, params);
    }

    @Override
    public int delete(String statementId, Object... params) throws SQLException, NoSuchFieldException, IllegalAccessException {
        MapperStatement mapperStatement = configuration.getMapperStatementMap().get(statementId);
        return simpleExecutor.executor(configuration, mapperStatement, params);
    }

    @Override
    public <T> T getMapper(Class<?> mapperClass) {
        return (T) Proxy.newProxyInstance(mapperClass.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                String methodName = method.getName();
                String className = method.getDeclaringClass().getName();
                String key = String.format("%s.%s", className, methodName);

                Type returnType = method.getGenericReturnType();
                // 如果返回值实现范性类型的参数化，则执行selectList
                if (returnType instanceof ParameterizedType) {
                    return selectList(key, args);
                } else if (methodName.contains(INSERT)) {
                    return insert(key, args);
                } else if (methodName.contains(UPDATE)) {
                    return update(key, args);
                } else if (methodName.contains(DELETE)) {
                    return delete(key, args);
                }
                return selectOne(key, args);
            }
        });
    }

    @Override
    public void commit() throws SQLException {
        simpleExecutor.commit();
    }

    @Override
    public void close() throws SQLException {
        simpleExecutor.close();
    }
}
